package com.toobigtofail.entities
{
	import com.toobigtofail.Game;
	import com.toobigtofail.utility.Util;
	
	import net.flashpunk.Entity;
	import net.flashpunk.FP;
	import net.flashpunk.Graphic;
	import net.flashpunk.Mask;
	import net.flashpunk.graphics.Image;
	import net.flashpunk.graphics.Spritemap;
	import net.flashpunk.tweens.misc.NumTween;
	import net.flashpunk.utils.Ease;
	
	public class Villager extends Entity
	{
		[Embed(source="/assets/gfx/personFrames.png")] private static const VILLAGER_PNG:Class;
		
		private var _isEnemy:Boolean;
		private var _isFighting:Boolean = false;
		
		private var _image:Spritemap;
		
		private var _rotateTween:NumTween = new NumTween;
		private var _speedX:Number = 20;
		private var _speedY:Number = 2.0;
		private var _isOnGround:Boolean = false;
		
		// Shared properties among all villagers
		//
		private static var _maxEnemySpeed:Number  = 40;
		private static var _maxPlayerSpeed:Number = 40;
		private static var _gravity:Number = 40;
		private static var _accelerationX:Number = 20;
		private static var _maxSpeedY:Number = 40;
		private static var _groundY:Number = 416;
		private static var _fightLine:int = int.MIN_VALUE;
		
		public function Villager(x:uint, isEnemy:Boolean=false)
		{
			_image = new Spritemap(VILLAGER_PNG, 16, 24);
			_image.add("run", [0,1,2,3,4,5],12,true);
			_image.centerOO()
			graphic = _image;
			
			setHitbox(_image.width - 8, _image.height);
			
			_isEnemy = isEnemy;
			this.x = x;
			this.y = _groundY + height;
			
			_image.flipped = _isEnemy;
			
			if (_fightLine == int.MIN_VALUE) {
				_fightLine = FP.width/2 + width/2;
			}
			
			_speedX = _maxPlayerSpeed;
			_speedY = 0;
			
			addTween(_rotateTween);
			
			super(x, y, graphic, mask);
		}
		
		override public function update():void
		{
			super.update();
			
			// apply gravity
			if (!_isOnGround) {
				if (_rotateTween.active) {
					_image.angle = _rotateTween.value;
				}
				
				_speedY = Math.min(_maxSpeedY, _speedY + (_gravity * FP.elapsed));
				y += _speedY * FP.elapsed;
				if (y + height > _groundY) {
					y = _groundY - height;
					_isOnGround = true;
				}
				
				_isFighting = false;
			}
			else {
				_rotateTween.active = false;
				_image.angle = 0;
				
				_image.play("run");
			
				_speedX = Math.min((_isEnemy ? _maxEnemySpeed : _maxPlayerSpeed), _speedX + (_accelerationX * FP.elapsed));
			}
			
			if (_isEnemy) {
				x -= _speedX * FP.elapsed;
				if (x < _fightLine) {
					x = _fightLine;
					_isFighting = true;
				}
			} else {
				x += _speedX * FP.elapsed;
				if (x > _fightLine - width) {
					x = _fightLine - width;
					_isFighting = true;
				}
			}
			
			if(_isFighting) {
				fight();
			}
		}

		private function fight():void
		{
			if (Util.random(0, 100) < 2) {
				smackBack();
			}
		}
		
		private function smackBack():void {
			var r:int = Util.random(1,60);
			
			_rotateTween.tween(0, _isEnemy ? -360 : 360, FP.scale(r, 1, 60, 2.5, 5), Ease.quadInOut);
			_rotateTween.start();
			
			_speedY = -(30 + r);
			_speedX = -(10 + r/3);
			
			_isOnGround = false;
		}
		
		// Public Getters and Setters
		//
		public static function get playerVelocity():Number { return _maxPlayerSpeed; }
		public static function set playerVelocity(v:Number):void { _maxPlayerSpeed = v; }
		
		public static function get enemyVelocity():Number { return _maxEnemySpeed; }
		public static function set enemyVelocity(v:Number):void { _maxEnemySpeed = v; }
		
		public static function get gravity():Number { return _gravity; }
		public static function set gravity(v:Number):void { _gravity = v; }
		
		public static function get fightLine():Number { return _fightLine; }
		public static function set fightLine(v:Number):void { _fightLine = v; }
	}
}